package com.markhsiu.httpserver.event.formparse;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.UploadContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import com.markhsiu.httpserver.event.HttpMethod;
import com.markhsiu.httpserver.event.Request;

public class MarkFileUpload extends FileUpload {

    public static class MarkHttpContext implements UploadContext {

        private Request request;

        public MarkHttpContext(Request request) {
            this.request = request;
        }

        @Override
        public long contentLength() {
            return request.getContentLength();
        }

        @Override
        public String getCharacterEncoding() {
            return request.getCharacterEncoding();
        }

        @Override
        public String getContentType() {
            return request.getContentType();
        }

        @Override
        public int getContentLength() {
            return (int) contentLength();
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return request.getInputStream();
        }
    }

    public static final boolean isMultipartContent(Request request) {
        return request.method() == HttpMethod.POST 
        		&& FileUploadBase.isMultipartContent(new MarkHttpContext(request));
    }

    public MarkFileUpload() {
        super(new DiskFileItemFactory());
    }

    public List<FileFormItem> parseRequest(Request request) throws FileUploadException {
    	List<FileItem> items = this.parseRequest(new MarkHttpContext(request));
    	List<FileFormItem> list = new ArrayList<>();
    	FileFormItem formItem = null;
    	for (FileItem item : items) {
    		list.add(convert(formItem, item));
		}
    	return list;
    }

    public Map<String, List<FileFormItem>> parseParameterMap(Request request) throws FileUploadException {
         List<FileItem> items = this.parseRequest(new MarkHttpContext(request));
    	 final Map<String, List<FileFormItem>> itemsMap = new HashMap<String, List<FileFormItem>>(items.size());

    	 FileFormItem formItem = null;
         for (FileItem item : items) {
             String fieldName = item.getFieldName();
             List<FileFormItem> mappedItems = itemsMap.get(fieldName);

             if (mappedItems == null) {
                 mappedItems = new ArrayList<FileFormItem>();
                 itemsMap.put(fieldName, mappedItems);
             }

             mappedItems.add(convert(formItem, item));
         }
         return itemsMap;
    }
    
    private FileFormItem convert(FileFormItem formItem, FileItem item){
    	if(formItem == null){
    		formItem = new FileFormItem();
    	}
    	
		formItem.setName(item.getName());
		formItem.setFeildName(item.getFieldName());
		formItem.setLength(item.getSize());
		formItem.setBody(item.get());
		if(item.isFormField()){
			formItem.setFileField(false);
		} else {
			formItem.setFileField(true);	
		}
		return formItem;
    }

    public FileItemIterator getItemIterator(Request request) throws FileUploadException, IOException {
        return super.getItemIterator(new MarkHttpContext(request));
    }
}